home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1997 February
/
EnigmA AMIGA RUN 15 (1997)(G.R. Edizioni)(IT)[!][issue 1997-02][PLANET CD V].iso
/
enigma
/
earcd
/
varie
/
uae-0_64.lha
/
uae-0.6.4
/
src
/
amiga.c
next >
Wrap
C/C++ Source or Header
|
1996-08-18
|
18KB
|
835 lines
/*
* UAE - The Un*x Amiga Emulator
*
* Amiga (native) specific support code; compiles with SAS/C 6.56,
* to get CyberGraphX support, add "DEFINE=_CYBERGFX" to the compiler
* flags in the smakefile. When running, hold down both Amiga keys
* to quit the emulation. The emulation also responds to ^C, which
* will abort it and to ^D which will reset it. Take care, the code
* appears to be very brittle and collapses easily if you switch
* screens. With CyberGraphX support enabled, the screen setup tries
* to be smart and falls back to standard screen update techniques
* if the screen to be opened does not belong to CyberGraphX. The
* 15/16/24 bit colour modes require that a graphics card like the
* CyberVision64 is installed that's not subject to byte ordering
* problems.
*
* (c) 1996 Olaf `Olsen' Barthel
*/
#include <intuition/intuitionbase.h>
#include <intuition/pointerclass.h>
#include <graphics/gfxbase.h>
#include <graphics/displayinfo.h>
#include <libraries/asl.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <dos/dosasl.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/asl_protos.h>
#include <pragmas/intuition_pragmas.h>
#include <pragmas/graphics_pragmas.h>
#include <pragmas/exec_pragmas.h>
#include <pragmas/dos_pragmas.h>
#include <pragmas/asl_pragmas.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#ifdef _CYBERGFX
#include <cybergraphics/cybergraphics.h>
#include <clib/cybergraphics_protos.h>
#include <pragmas/cybergraphics_pragmas.h>
#endif
/****************************************************************************/
#include "custom.h"
#include "options.h"
#include "keybuf.h"
#include "autoconf.h"
#include "xwin.h"
/****************************************************************************/
extern struct ExecBase *SysBase;
extern struct DosLibrary *DOSBase;
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Library *AslBase;
struct Library *CyberGfxBase;
/****************************************************************************/
STATIC struct Screen *Screen;
STATIC struct Window *Window;
STATIC Object *Pointer;
STATIC ULONG WindowMask;
STATIC struct RastPort *TempRPort,
*RenderPort;
STATIC struct BitMap *BitMap;
STATIC UBYTE *Line;
STATIC LONG ScreenHeight,
ScreenWidth;
/****************************************************************************/
int buttonstate[3];
int lastmx, lastmy;
int newmousecounters;
long int xcolors[4096];
struct vidbuf_description gfxvidinfo;
/****************************************************************************/
void m68k_reset(void);
/****************************************************************************/
STATIC VOID
AmigaCleanup(VOID)
{
if(BitMap)
{
WaitBlit();
FreeBitMap(BitMap);
BitMap = NULL;
}
if(TempRPort)
{
FreeVec(TempRPort);
TempRPort = NULL;
}
if(Line)
{
FreeVec(Line);
Line = NULL;
}
if(Window)
{
CloseWindow(Window);
Window = NULL;
}
if(Pointer)
{
DisposeObject(Pointer);
Pointer = NULL;
}
if(Screen)
{
CloseScreen(Screen);
Screen = NULL;
}
if(AslBase)
{
CloseLibrary(AslBase);
AslBase = NULL;
}
if(GfxBase)
{
CloseLibrary(GfxBase);
GfxBase = NULL;
}
if(IntuitionBase)
{
CloseLibrary(IntuitionBase);
IntuitionBase = NULL;
}
if(CyberGfxBase)
{
CloseLibrary(CyberGfxBase);
CyberGfxBase = NULL;
}
}
void
flush_line(int y)
{
if(!CyberGfxBase)
{
if(y >= 0 && y < ScreenHeight)
{
char *linebuf = y * gfxvidinfo.rowbytes + gfxvidinfo.bufmem;
CopyMem(linebuf,Line,ScreenWidth);
WritePixelLine8(RenderPort,0,y,ScreenWidth,Line,TempRPort);
}
}
}
void
flush_block(int ystart,int ystop)
{
if(!CyberGfxBase)
{
if(ystart < 0)
ystart = 0;
else
{
if(ystart >= ScreenHeight)
ystart = ScreenHeight - 1;
}
if(ystop < 0)
ystop = 0;
else
{
if(ystop >= ScreenHeight)
ystop = ScreenHeight - 1;
}
if(ystart <= ystop)
{
char *mem;
int i;
mem = ystart * gfxvidinfo.rowbytes + gfxvidinfo.bufmem;
for(i = ystart ; i <= ystop ; i++, mem += gfxvidinfo.rowbytes)
{
CopyMem(mem,Line,ScreenWidth);
WritePixelLine8(RenderPort,0,i,ScreenWidth,Line,TempRPort);
}
}
}
}
void
flush_screen(int ystart,int ystop)
{
}
static int
get_color(int r,int g,int b,long *cnp)
{
ULONG Red,Green,Blue;
LONG Pen;
Red = 0x11111111 * r;
Green = 0x11111111 * g;
Blue = 0x11111111 * b;
Pen = ObtainBestPen(Screen->ViewPort.ColorMap,Red,Green,Blue,
OBP_Precision,PRECISION_IMAGE,
TAG_DONE);
if(Pen == -1)
return(0);
else
{
*cnp = Pen;
return(1);
}
}
int
graphics_init(void)
{
struct ScreenModeRequester *ScreenRequest;
ULONG DisplayID;
struct BitMap PointerBitMap;
UWORD PointerLine;
struct DimensionInfo Dims;
BOOL GotOne;
LONG Depth;
int vsize;
atexit(AmigaCleanup);
vsize = correct_aspect ? 2*numscrlines : numscrlines;
if(!(gfxvidinfo.bufmem = malloc(800 * vsize)))
{
fprintf(stderr,"Sorry guv'nor, not enough memory for the line buffer.\n");
return(0);
}
memset(gfxvidinfo.bufmem,0,800 * vsize);
gfxvidinfo.rowbytes = 800;
gfxvidinfo.pixbytes = 1;
gfxvidinfo.maxblocklines = 100;
gfxvidinfo.maxline = 100000; /* ??? */
if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",39)))
{
fprintf(stderr,"Sorry guv'nor, unable to open intuition.library v39.\n");
return(0);
}
if(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",39)))
{
fprintf(stderr,"Sorry guv'nor, unable to open graphics.library v39.\n");
return(0);
}
DisplayID = INVALID_ID;
GotOne = FALSE;
while((DisplayID = NextDisplayInfo(DisplayID)) != INVALID_ID)
{
if(GetDisplayInfoData(NULL,(APTR)&Dims,sizeof(Dims),DTAG_DIMS,DisplayID))
{
if(Dims.MaxDepth >= 8)
{
GotOne = TRUE;
break;
}
}
}
if(!GotOne)
{
fprintf(stderr,"Sorry guv'nor, your Amiga needs an AA chip set or a graphics card.\n");
return(0);
}
if(!(AslBase = OpenLibrary("asl.library",38)))
{
fprintf(stderr,"Sorry guv'nor, unable to open asl.library v38.\n");
return(0);
}
if(!(ScreenRequest = AllocAslRequest(ASL_ScreenModeRequest,NULL)))
{
fprintf(stderr,"Sorry guv'nor, unable to allocate screen mode requester.\n");
return(0);
}
if(AslRequestTags(ScreenRequest,
ASLSM_TitleText, "Select screen display mode",
ASLSM_MinDepth, 8,
TAG_DONE))
{
DisplayID = ScreenRequest->sm_DisplayID;
GetDisplayInfoData(NULL,(APTR)&Dims,sizeof(Dims),DTAG_DIMS,DisplayID);
Depth = Dims.MaxDepth;
if(Depth > 8)
color_mode = 1;
}
else
DisplayID = INVALID_ID;
FreeAslRequest(ScreenRequest);
CloseLibrary(AslBase);
AslBase = NULL;
if(DisplayID == INVALID_ID)
return(0);
if(!(Screen = OpenScreenTags(NULL,
SA_DisplayID, DisplayID,
SA_Depth, Depth,
SA_Interleaved, TRUE,
SA_ShowTitle, FALSE,
SA_BackFill, LAYERS_NOBACKFILL,
SA_Quiet, TRUE,
SA_Behind, TRUE,
SA_SharePens, TRUE,
SA_Exclusive, TRUE,
SA_Draggable, FALSE,
TAG_DONE)))
{
fprintf(stderr,"Sorry guv'nor, unable to open the screen.\n");
return(0);
}
ScreenWidth = Screen->Width;
ScreenHeight = Screen->Height;
if(ScreenWidth > 800)
ScreenWidth = 800;
if(ScreenHeight > 600)
ScreenHeight = 600;
#ifdef _CYBERGFX
if(CyberGfxBase = OpenLibrary("cybergraphics.library",40))
{
if(!IsCyberModeID(DisplayID) || ScreenHeight < vsize)
{
CloseLibrary(CyberGfxBase);
CyberGfxBase = NULL;
}
}
#endif
if(!(BitMap = AllocBitMap(Screen->Width,1,8,BMF_CLEAR|BMF_MINPLANES,Screen->RastPort.BitMap)))
{
fprintf(stderr,"Sorry guv'nor, unable to allocate BitMap.\n");
return(0);
}
if(!(TempRPort = AllocVec(sizeof(struct RastPort),MEMF_ANY|MEMF_PUBLIC)))
{
fprintf(stderr,"Sorry guv'nor, unable to allocate RastPort.\n");
return(0);
}
if(!(Line = AllocVec((Screen->Width + 15) & ~15,MEMF_ANY|MEMF_PUBLIC)))
{
fprintf(stderr,"Sorry guv'nor, unable to allocate raster buffer.\n");
return(0);
}
CopyMem(&Screen->RastPort,TempRPort,sizeof(struct RastPort));
TempRPort->Layer = NULL;
TempRPort->BitMap = BitMap;
PointerLine = 0x0000;
InitBitMap(&PointerBitMap,2,16,1);
PointerBitMap.Planes[0] = (PLANEPTR)&PointerLine;
PointerBitMap.Planes[1] = (PLANEPTR)&PointerLine;
if(!(Pointer = NewObject(NULL,POINTERCLASS,
POINTERA_BitMap, &PointerBitMap,
POINTERA_WordWidth, 1,
TAG_DONE)))
{
fprintf(stderr,"Sorry guv'nor, unable to allocate blank mouse pointer.\n");
return(0);
}
if(!(Window = OpenWindowTags(NULL,
WA_Width, Screen->Width,
WA_Height, Screen->Height,
WA_CustomScreen, Screen,
WA_Backdrop, TRUE,
WA_Borderless, TRUE,
WA_BackFill, LAYERS_NOBACKFILL,
WA_RMBTrap, TRUE,
WA_IDCMP, IDCMP_RAWKEY|IDCMP_MOUSEBUTTONS|IDCMP_MOUSEMOVE,
WA_Pointer, Pointer,
WA_ReportMouse, TRUE,
TAG_DONE)))
{
fprintf(stderr,"Sorry guv'nor, unable to open the window.\n");
return(0);
}
RenderPort = &Screen->RastPort;
WindowMask = 1UL << Window->UserPort->mp_SigBit;
SetRast(RenderPort,0);
switch(Depth)
{
case 8:
alloc_colors256(get_color);
break;
case 15:
alloc_colors64k(5,5,5,10,5,0);
break;
case 16:
alloc_colors64k(5,6,5,11,5,0);
break;
case 24:
case 32:
alloc_colors64k(8,8,8,16,8,0);
break;
}
ScreenToFront(Screen);
ActivateWindow(Window);
buttonstate[0] = buttonstate[1] = buttonstate[2] = 0;
lastmx = lastmy = 0;
newmousecounters = 0;
#ifdef _CYBERGFX
if(CyberGfxBase)
{
free(gfxvidinfo.bufmem);
gfxvidinfo.bufmem = (char *)GetCyberMapAttr(Screen->RastPort.BitMap,CYBRMATTR_DISPADR);
gfxvidinfo.rowbytes = GetCyberMapAttr(Screen->RastPort.BitMap,CYBRMATTR_XMOD);
gfxvidinfo.pixbytes = GetCyberMapAttr(Screen->RastPort.BitMap,CYBRMATTR_BPPIX);
}
#endif
return(1);
}
void
graphics_leave(void)
{
AmigaCleanup();
}
void
handle_events(void)
{
ULONG Mask;
Mask = SetSignal(0,SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D|WindowMask);
if(Mask & SIGBREAKF_CTRL_C)
{
PrintFault(ERROR_BREAK,"uae");
exit(RETURN_WARN);
}
if(Mask & SIGBREAKF_CTRL_D)
m68k_reset();
if(Mask & WindowMask)
{
struct IntuiMessage *IMsg;
ULONG MsgClass;
UWORD MsgCode;
WORD MsgX,MsgY;
WORD Button;
BOOL Quit;
newmousecounters = 0;
Quit = FALSE;
while(IMsg = (struct IntuiMessage *)GetMsg(Window->UserPort))
{
MsgClass = IMsg->Class;
MsgCode = IMsg->Code;
MsgX = IMsg->MouseX;
MsgY = IMsg->MouseY;
if((IMsg->Qualifier & (IEQUALIFIER_LCOMMAND|IEQUALIFIER_RCOMMAND)) == (IEQUALIFIER_LCOMMAND|IEQUALIFIER_RCOMMAND))
Quit = TRUE;
ReplyMsg(IMsg);
switch(MsgClass)
{
case IDCMP_RAWKEY:
if(MsgCode & IECODE_UP_PREFIX)
record_key(((MsgCode & ~IECODE_UP_PREFIX) << 1) | 1);
else
record_key((MsgCode) << 1);
break;
case IDCMP_MOUSEBUTTONS:
switch(MsgCode & ~IECODE_UP_PREFIX)
{
case IECODE_LBUTTON:
Button = 0;
break;
case IECODE_MBUTTON:
Button = 1;
break;
case IECODE_RBUTTON:
Button = 2;
break;
}
if(MsgCode & IECODE_UP_PREFIX)
buttonstate[Button] = 0;
else
buttonstate[Button] = 1;
break;
case IDCMP_MOUSEMOVE:
lastmx = MsgX;
lastmy = MsgY;
newmousecounters = 1;
break;
}
}
if(Quit)
exit(RETURN_OK);
}
}
int
debuggable(void)
{
return 1;
}
int
needmousehack(void)
{
return 1;
}
void
LED(int on)
{
}
/****************************************************************************/
int quit_program;
int
gui_init(void)
{
quit_program = 0;
}
void
gui_exit(void)
{
}
void
gui_led(int led, int on)
{
}
void
gui_filename(int num, char *name)
{
}
void
gui_handle_events(void)
{
}
/****************************************************************************/
int opterr = 1; /* error => print message */
int optind = 1; /* next argv[] index */
char *optarg = NULL; /* option parameter if any */
static int
Err( name, mess, c ) /* returns '?' */
char *name; /* program name argv[0] */
char *mess; /* specific message */
int c; /* defective option letter */
{
if ( opterr )
(void) fprintf( stderr,
"%s: %s -- %c\n",
name, mess, c
);
return '?'; /* erroneous-option marker */
}
int
getopt( argc, argv, optstring ) /* returns letter, '?', EOF */
int argc; /* argument count from main */
char *argv[]; /* argument vector from main */
char *optstring; /* allowed args, e.g. "ab:c" */
{
static int sp = 1; /* position within argument */
register int osp; /* saved `sp' for param test */
register int c; /* option letter */
register char *cp; /* -> option in `optstring' */
optarg = NULL;
if ( sp == 1 ) /* fresh argument */
if ( optind >= argc /* no more arguments */
|| argv[optind][0] != '-' /* no more options */
|| argv[optind][1] == '\0' /* not option; stdin */
)
return EOF;
else if ( strcmp( argv[optind], "--" ) == 0 )
{
++optind; /* skip over "--" */
return EOF; /* "--" marks end of options */
}
c = argv[optind][sp]; /* option letter */
osp = sp++; /* get ready for next letter */
if ( argv[optind][sp] == '\0' ) /* end of argument */
{
++optind; /* get ready for next try */
sp = 1; /* beginning of next argument */
}
if ( c == ':' /* optstring syntax conflict */
|| (cp = strchr( optstring, c )) == NULL /* not found */
)
return Err( argv[0], "illegal option", c );
if ( cp[1] == ':' ) /* option takes parameter */
{
if ( osp != 1 )
return Err( argv[0],
"option must not be clustered",
c
);
if ( sp != 1 ) /* reset by end of argument */
return Err( argv[0],
"option must be followed by white space",
c
);
if ( optind >= argc )
return Err( argv[0],
"option requires an argument",
c
);
optarg = argv[optind]; /* make parameter available */
++optind; /* skip over parameter */
}
return c;
}
/****************************************************************************/
static void usage(void)
{
printf("UAE - The Un*x Amiga emulator\n");
printf("Summary of command-line options:\n");
printf(" -h : Print help\n");
printf(" -m VOLNAME:mount_point : mount file system at <mount point> as AmigaDOS\n"
" volume VOLNAME:\n");
printf(" -M VOLNAME:mount_point : like -m, but mount read-only\n");
printf(" -a : Don't mount the harddisk file automatically.\n"
" Useful only for testing.\n");
printf(" -S : Turn off sound support (if it is configured)\n");
printf(" -s : Emulate 1 MB slow memory at 0xC00000\n");
printf(" -F n : Emulate n MB fast memory at 0x200000\n");
printf(" -f n : Set the frame rate to 1/n\n");
printf(" -x : Use visible cross-hair cursor (X Windows version)\n");
printf(" -D : Start up the built-in debugger\n");
printf(" -[0123] file : Use file instead of df[0123].adf as disk image file\n");
printf(" -r file : Use file as ROM image instead of kick.rom\n");
printf(" -J : Fake joystick emulation with the numeric pad.\n");
printf(" -g : Turn on gfx-lib replacement.\n");
printf(" -d mode : Select resolution with the mode parameter.\n");
printf(" -H mode : Set the number of colors with the mode parameter.\n");
printf("\n");
printf("Valid resolutions: 0 (320x200); 1 (320x240); 2 (320x400); 3 (800x600);\n"
" 4 (800x600, correct aspect)\n"
"Valid color modes: 0 (256 colors); 1 (32768 colors); 2 (65536 colors)\n"
"UAE may choose to ignore the color mode/resolution setting.\n");
}
void parse_cmdline(int argc, char **argv)
{
extern ULONG fastmem_size;
int c;
while(((c = getopt(argc, argv, "l:Df:gd:hxF:asSJm:M:0:1:2:3:r:H:")) != EOF)) switch(c) {
case 'h': usage(); exit(0);
case '0': strncpy(df0, optarg, 255); df0[255] = 0; break;
case '1': strncpy(df1, optarg, 255); df1[255] = 0; break;
case '2': strncpy(df2, optarg, 255); df2[255] = 0; break;
case '3': strncpy(df3, optarg, 255); df3[255] = 0; break;
case 'r': strncpy(romfile, optarg, 255); romfile[255] = 0; break;
case 'm':
case 'M':
{
/* mount file system (repeatable)
* syntax: [-m | -M] VOLNAME:/mount_point
* example: -M CDROM:/cdrom -m UNIXFS:./disk
*/
static int mount_seen = 0;
char buf[256];
char *s2;
int readonly = (c == 'M');
if (mount_seen)
fprintf(stderr, "warning: multiple mounts confuse Kickstart 1.3\n");
mount_seen = 1;
strncpy(buf, optarg, 255); buf[255] = 0;
s2 = strchr(buf, ':');
if(s2) {
*s2++ = '\0';
add_filesys_unit(buf, s2, readonly);
} else {
fprintf(stderr, "Usage: [-m | -M] VOLNAME:/mount_point\n");
}
}
break;
case 'S': produce_sound = 0; break;
case 'f': framerate = atoi(optarg); break;
case 'x': use_xhair = 1; break;
case 'D': use_debugger = 1; break;
case 'J': fake_joystick = 1; break;
case 'a': automount_uaedev = 0; break;
case 's': use_slow_mem = 1; break;
case 'g': use_gfxlib = 1; break;
case 'F':
fastmem_size = atoi(optarg) * 0x100000;
if (fastmem_size != 0x100000 && fastmem_size != 0x200000
&& fastmem_size != 0x400000 && fastmem_size != 0x800000)
{
fastmem_size = 0;
fprintf(stderr, "Unsupported fastmem size!\n");
}
break;
case 'd':
screen_res = atoi(optarg);
if (screen_res >= 0 && screen_res <= 4) {
} else {
fprintf(stderr, "Bad video mode selected. Using default.\n");
screen_res = 3;
}
/*dont_want_aspect = screen_res != 4;*/
use_lores = screen_res < 3;
break;
case 'H':
color_mode = atoi(optarg);
if (color_mode < 0 || color_mode > 2) {
fprintf(stderr, "Bad color mode selected. Using default.\n");
color_mode = 0;
}
break;
}
}